package org.litemall.netty.service;

import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.litemall.netty.nettyDoman.AdminChannel;
import org.litemall.netty.nettyDoman.UserChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @Author Lizr socket鏈接后保存起來
 * @Description
 * @CreateTime 2021-10-28 上午 11:57
 **/
public class ChannelSupervise {
    private static final Logger logger = LoggerFactory.getLogger(ChannelSupervise.class);
    private   static ChannelGroup GlobalGroup=new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    /**
     * 用戶存储 后台管理员信息群组
     */
    public static ChannelGroup AdminGloup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    public static ConcurrentMap<String, AdminChannel> AdminCannelMap = new ConcurrentHashMap<>();
    // 用管理员id 维护 AdminCannelMap
    public static ConcurrentMap<Integer, String> AdminChannelIdMap = new ConcurrentHashMap<>();

    /**
     * 用于存储 普通用户 信息群组
     */
    private static ChannelGroup UserGloup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    public static ConcurrentMap<String, UserChannel> UserCannelMap = new ConcurrentHashMap<>();
    private static ConcurrentMap<Integer, String> UserChannelIdMap = new ConcurrentHashMap<>();

    public static boolean checkAdminContainsKey(Channel channel){
        boolean Contains = false;
        if(AdminGloup.contains(channel) && AdminCannelMap.containsKey(channel.id().asShortText())){
            Contains = true;
        }
        return Contains;
    }

    public static boolean checkUserContainsKey(Channel channel){
        boolean Contains = false;
        if(UserGloup.contains(channel) && UserCannelMap.containsKey(channel.id().asShortText())){
            Contains = true;
        }
        return Contains;
    }
    /**
     * 保存管理员socket连接 并且返回
     * @param channel 链接
     */
    public static void addAdminChannel(AdminChannel channel){
        logger.info("管理员加入socket链接, 链接ID: [{}], 管理员ID: [{}]", channel.getChannelId(), channel.getAdminId());
        // 往群组添加一个管理员socket管道
        AdminGloup.add(channel.getChannel());
        AdminCannelMap.put(channel.getChannel().id().asShortText(), channel);
        AdminChannelIdMap.put(channel.getAdminId(), channel.getChannel().id().asShortText());
        getAdminId(channel.getChannel().id().asShortText());
    }

    /**
     * 保存用户socket连接 并且返回
     * @param channel 链接
     */
    public static void addUserChannel(UserChannel channel){
        logger.info("用户加入socket链接, 链接ID: [{}], 用户ID: [{}]", channel.getChannelId(), channel.getUserId());
        // 往群组添加一个用户socket管道
        UserGloup.add(channel.getChannel());
        UserCannelMap.put(channel.getChannel().id().asShortText(), channel);
        UserChannelIdMap.put(channel.getUserId(), channel.getChannel().id().asShortText());
        getUserId(channel.getChannel().id().asShortText());
    }

    /**
     * 移除管理员链接信息
     * @param channel 链接
     */
    public static void removeAdminChannel(Channel channel){
        try {
            logger.info("管理员关闭socket链接, 链接ID: [{}], 管理员ID: [{}]", AdminCannelMap.get(channel.id().asShortText()).getChannelId(), AdminCannelMap.get(channel.id().asShortText()).getAdminId());
            AdminGloup.remove(channel);
            AdminCannelMap.remove(channel.id().asShortText());
            AdminChannelIdMap.remove(getAdminId(channel.id().asShortText()));
        }catch (Exception e){}
    }

    /**
     * 移除用户链接信息
     * @param channel 链接
     */
    public static void removeUserChannel(Channel channel){
        try {
            logger.info("用户关闭socket链接, 链接ID: [{}], 用户ID: [{}]", UserCannelMap.get(channel.id().asShortText()).getChannelId(), UserCannelMap.get(channel.id().asShortText()).getUserId());
            UserGloup.remove(channel);
            UserCannelMap.remove(channel.id().asShortText());
            UserChannelIdMap.remove(getAdminId(channel.id().asShortText()));
        }catch (Exception e){}
    }

    /**
     * 根据channel Id获取管理员id
     * @param value channel Id
     * @return
     */
    public static Integer getAdminId(String value){
        Integer adminId = null;
        Set<Map.Entry<Integer, String>> entrySet =  AdminChannelIdMap.entrySet();
        for (Map.Entry<Integer, String> s : entrySet) {
            if(s.getValue().equals(value)){
                adminId = s.getKey();
                break;
            }
        }
        logger.info("根据channelId获取 管理员Id: [{}]", adminId);
        return adminId;
    }

    /**
     * 根据channel Id获取用户id
     * @param value channel Id
     * @return
     */
    public static Integer getUserId(String value){
        Integer userId = null;
        Set<Map.Entry<Integer, String>> entrySet =  UserChannelIdMap.entrySet();
        for (Map.Entry<Integer, String> s : entrySet) {
            if(s.getValue().equals(value)){
                userId = s.getKey();
                break;
            }
        }
        logger.info("根据channelId获取 用户Id: [{}]", userId);
        return userId;
    }

    /**
     * 向所有 管理员发送信息
     * @param tws 文本格式信息
     */
    public static void sendAllAdminMessage(TextWebSocketFrame tws){
        AdminGloup.writeAndFlush(tws);
    }

    /**
     * 向指定 管理员发送信息
     * @param channelId 连接id
     */
    public static void sendAdminMessageById(String channelId, TextWebSocketFrame tws){
        if(AdminCannelMap.containsKey(channelId)){
            AdminChannel AdminChannel = AdminCannelMap.get(channelId);
            logger.info("通过socket像管理员发送信息, 链接ID: [{}], 管理员ID: [{}]", AdminChannel.getChannelId(), AdminChannel.getAdminId());
        }
    }

    /**
     * 向指定 用户发送信息
     * @param userId 用户ID
     */
    public static void sendUserMessageById(Integer userId, TextWebSocketFrame tws){
        try {
            if(UserChannelIdMap.containsKey(userId)){
                String channelId = UserChannelIdMap.get(userId);
                UserChannel UserChannel = UserCannelMap.get(channelId);
                UserChannel.getChannel().writeAndFlush(tws);
                logger.info("通过socket向用户发送信息, 链接ID: [{}], 用户ID: [{}]", UserChannel.getChannelId(), UserChannel.getUserId());
            }
        }catch (Exception e){
            logger.error("通过用户ID 发送消息失败, 原因: [{}], 用户ID: [{}]", e.getMessage(), userId);
        }

    }


    /*
    private  static ConcurrentMap<String, ChannelId> ChannelMap=new ConcurrentHashMap();
    public  static void addChannel(Channel channel){
        GlobalGroup.add(channel);
        ChannelMap.put(channel.id().asShortText(),channel.id());
    }
    public static void removeChannel(Channel channel){
        GlobalGroup.remove(channel);
        ChannelMap.remove(channel.id().asShortText());
    }
    public static  Channel findChannel(String id){
        return GlobalGroup.find(ChannelMap.get(id));
    }
    public static void send2All(TextWebSocketFrame tws){
        GlobalGroup.writeAndFlush(tws);
    }

     */
}
